本系列文章已重新編修,並在加入部分 ES6 新篇章後集結成書,有興趣的朋友可至天瓏書局選購,感謝大家支持。
購書連結 https://www.tenlong.com.tw/products/9789864344130
讓我們再次重新認識 JavaScript!
昨天看到朋友傳了一個在 stack overflow 看到的有趣問題:
Can (a ==1 && a== 2 && a==3) ever evaluate to true?
發問的人表示,他去參加了某個公司的面試,面試官問他要怎麼樣讓 JavaScript 的
(a == 1 && a == 2 && a == 3)
結果為 true
。
也就是說,希望結果會像這樣:
來,猜猜看,到底施了什麼魔法才能讓判斷式 (a == 1 && a == 2 && a == 3)
成立?
想一想,先別急著看連結內的解答。
.
.
.
.
.
.
有答案了嗎? 好,我們來看看原文的最佳解答是怎麼做的吧!
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
看出來為什麼了嗎?
複習一下,我們在「重新認識 JavaScript」系列文的
兩篇文章當中,曾經為各位介紹過「比較運算子」與「Boolean 的自動轉型」特性對吧?
先看 if
的條件判斷式
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
因為 &&
運算子會先將左側的結果轉換成 Boolean
,並檢查是否為 ture
,如果為 true
再將 &&
右側的值回傳。
所以像上面這樣的寫法,我們可以拆分成:
// 當 a == 1, a == 2, a == 3 都成立時才執行 console.log
if( a == 1 ) {
if( a == 2 ) {
if( a == 3 ) {
console.log('Hello World!');
}
}
}
注意到了嗎?
這裡有個重點, if
判斷式內的檢查是用 ==
而非 ===
。
換句話說,當我們在做 ( a == 1 )
的判斷時,這個 a
會被自動轉型成「字串」的型態再做判斷。 那麼,來看看 a
。
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
這裡可以看到 a
是個物件的型態。 系列文曾提過,在物件的情況下,會先透過物件的 valueOf()
方法先求得對應的數值,若物件沒有 valueOf()
方法的話,則會透過 toString()
轉型再進行比較。
好,所以說 a.toString()
會得到什麼? a.i++
。
a.i
的初始值是 1
,所以 a.i++
回傳的結果是什麼? 還是 1
。 (注意 ++
的位置)
所以第一關 (a == 1)
的結果通過了。
由於因為剛剛執行了 a.i++
,所以此時 a.i
實質的結果是 2
。
而第二關的 ( a == 2 )
又會再做一次 a.i++
,得到的結果是 2
,所以又通過了。
那麼第三關的 ( a == 3 )
相信不用解說,當然也會得到 3
。
於是最後就完成了:
(a == 1 && a == 2 && a == 3) === true
這樣的結果了。
平常工作如果看到這樣程式的話,我一定會大罵花惹發,但是以觀念測試的角度來說,我覺得這是個不錯的情境題喔。
這篇 Stackflow 的問答討論熱度好像很高,今天到哪裡都看的到
(() => {
"use strict";
Object.defineProperty(this, "a", {
"get": () => {
Object.defineProperty(this, "a", {
"get": () => {
Object.defineProperty(this, "a", {
"get": () => {
return 3;
}
});
return 2;
},
configurable: true
});
return 1;
},
configurable: true
});
if (a == 1 && a == 2 && a == 3) {
document.body.append("Yes, it’s possible.");
}
})();
這個真不知道該說是非常認真還是怎樣了哈哈
每 get 一次就複寫 get return 出來的 value 的意思 XD
借用這個方法改寫,把 function 提出來,以後就可以大量製造這種 value 了(誤
可惜XD node 無法改,只好用 valueOf,只有轉型時才能用